﻿
using System;

using System.Text;
using OAuth.Net.Mobile.Common;
using OpenNETCF.Security.Cryptography;
using System.Net;

namespace OAuth.Net.Mobile.Components
{
  public class HmacSha1SigningProvider
      : ISigningProvider
  {

    /// <summary>
    /// This signing provider provides HMAC-SHA1 signing
    /// </summary>        
    public string SignatureMethod
    {
      get { return "HMAC-SHA1"; }
    }

    /// <summary>
    /// The HMAC-SHA1 signature method has no pre-conditions
    /// </summary>
    /// <param name="request">The HTTP request</param>
    /// <returns>True</returns>
    public virtual bool CheckRequest(HttpWebRequest request)
    {
      return true;
    }

    /// <summary>
    /// Computes the HMAC-SHA1 signature using <paramref name="signatureBase"/> as the text
    /// and <paramref name="consumerSecret"/>&amp;<paramref name="tokenSecret"/> parameter 
    /// encoded as the key.
    /// </summary>
    /// <param name="signatureBase">The signature base string (see OAuth Core 1.0 §9.1)</param>
    /// <param name="consumerSecret">The consumer secret</param>
    /// <param name="tokenSecret">The token secret, if present</param>
    /// <returns>The computed signature</returns>
    public virtual string ComputeSignature(string signatureBase, string consumerSecret, string tokenSecret)
    {

      using (HMACSHA1 crypto = new HMACSHA1())
      {
      
        string key = Rfc3986.Encode(consumerSecret) + "&" + Rfc3986.Encode(tokenSecret);
        byte[] bkey = Encoding.ASCII.GetBytes(key);
        // Keys longer than 60 characters do not work with OpenNetCF
        if (bkey.Length > 60)
        {
          bkey = (new System.Security.Cryptography.SHA1CryptoServiceProvider()).ComputeHash(bkey);
        }

        crypto.Key = bkey;
        string hash = Convert.ToBase64String(crypto.ComputeHash(Encoding.ASCII.GetBytes(signatureBase)));
        crypto.Clear();

        return hash;      
      }
    }
   
    public virtual bool CheckSignature(string signatureBase, string signature, string consumerSecret, string tokenSecret)
    {
      string expectedSignature = this.ComputeSignature(
          signatureBase,
          consumerSecret,
          tokenSecret);

      string actualSignature = Rfc3986.Decode(signature);

      return expectedSignature == actualSignature;
    }
  }
}
